package cn.edu.hyit.hjq.volunteems.backend.utils;

import io.jsonwebtoken.*;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;

@Data
@Component
public class JwtUtils {
    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration}")
    private long expiration;

    /**
     * 根据用户ID和角色列表生成JWT令牌
     *
     * @param userId 用户唯一标识符，用于设置JWT的主体
     * @return 返回生成的JWT字符串
     */
    public String generateToken(String userId) {
        // 创建一个Claims对象，设置JWT的主体为用户ID
        Claims claims = Jwts.claims().setSubject(userId);

        // 创建密钥对象
        Key key = new SecretKeySpec(secret.getBytes(), SignatureAlgorithm.HS512.getJcaName());

        return Jwts.builder()
                .setClaims(claims)
//                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .signWith(key)  // 使用 Key 对象签名
                .compact();
    }

    /**
     * 解析 JWT 令牌
     * 本方法使用 JWT 库解析传入的令牌字符串，并验证其签名的合法性
     * 解析成功后，返回令牌中包含的用户信息和权限等声明
     *
     * @param token 需要解析的 JWT 令牌字符串
     * @return 解析后的用户信息和权限等声明
     */
    public Claims parseToken(String token) {
        // 构建 Key 对象用于签名验证
        Key key = new SecretKeySpec(secret.getBytes(), SignatureAlgorithm.HS512.getJcaName());

        return Jwts.parserBuilder()
                .setSigningKey(key)  // 使用 Key 对象代替 String
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 验证令牌有效性
     * 该方法尝试解析JWT令牌，并验证其签名、格式和到期时间等
     * 如果令牌有效，方法返回true；如果令牌无效或解析过程中出现异常，方法返回false
     *
     * @param token 待验证的JWT令牌
     * @return 如果令牌有效返回true，否则返回false
     */
    public boolean validateToken(String token) {
        try {
            Key key = new SecretKeySpec(secret.getBytes(), SignatureAlgorithm.HS512.getJcaName());

            Jwts.parserBuilder()
                    .setSigningKey(key)  // 使用 Key 对象代替 String
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}